package com.cskaoyan.javase.string._2constantpool;

/**
 * @description: 字符串常量池
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * String s1 = "我是神";
 * String s2 = "我是神";
 * String s3 = new String("我是神");
 * 这三个String引用指向的对象有几个?有什么区别?
 * 只有两个对象,其中s1和s2指向同一个对象,s3是独立的对象和s1,s2不同
 *
 * 字符串的分配和其他对象分配一样，是需要消耗高昂的时间和空间的，而且字符串使用的非常多
 * JVM为了提高性能和减少内存的开销，在实例化字符串对象的时候进行了一些优化：
 *      像双引号引起来的字符串字面值"hello",它除了是一个常量外,它还是一个String对象,并且是一个编译器都知道的对象
 *      字符串常量在程序的编译期间就能够确定它的值,所以在编译时期就能够加入"静态常量池",随着JVM执行,在类加载过程中
 *      如果类中存在字符串字面值常量,会直接从"静态常量池"中读取并加入"字符串常量池"(字符串常量池在堆上)
 *
 * 于是:
 *      每当创建字符串常量对象时，JVM会首先检查字符串常量池，如果该字符串对象已经存在常量池中，那么就直接返回常量池中的实例引用。如果字符串对象不存在于常量池中，就会实例化该字符串并且将其放到常量池中。
 *
 * 由于String对象不可变,所以String对象是可以被共享的,所以就有了字符串常量池去共享字符串对象的概念
 * 字符串是JVM堆内存中最多的对象，尽量减少它们的创建，能够节省堆内存空间，也能提升JVM运行效率。
 *
 * 除此之外，不可变的对象往往都会更安全（在网络传输种不至于随意被更改），特别的String对象不可变后效率提升（字符串不可变不需要频繁计算hashCode()值，所以String是Map中最常见的key）
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        String s1 = "我是神";
        String s2 = "我是神";
        System.out.println("我是神".length());
        System.out.println(s1 == s2);
        String s3 = new String("我是神");
        System.out.println(s3);
        System.out.println(s1 == s3);
    }
}
